#include <iostream>
#include <vsomeip\vsomeip.hpp>
#include <memory>
#include <condition_variable>
#include <mutex>


#define SERVICE_ID 0x1234
#define SERVICE_INSTANCE_ID 0x5678
#define SERVICE_METHOD_ID 0x0001
#define SERVICE_SET_METHOD_ID 0x0002
#define SERVICE_GET_METHOD_ID 0x0003s
#define SERVICE_EVENT_GROUP_ID 0x4465
#define SERVICE_EVENT_ID 0x8778

using namespace std;
using namespace vsomeip;

shared_ptr<application> app;
std::mutex notify_mutex_;
std::condition_variable notify_condition_;
bool is_offered = false;

void on_message_cbk(const std::shared_ptr<vsomeip::message> &_request)
{
    // Create a response based upon the request
    std::shared_ptr<vsomeip::message> resp = vsomeip::runtime::get()->create_response(_request);

    // Construct string to send back
    std::string str("Hello ");
    str.append(
            reinterpret_cast<const char*>(_request->get_payload()->get_data()),
            0, _request->get_payload()->get_length());

    // Create a payload which will be sent back to the client
	cout << "Receive: " << str << endl;
    std::shared_ptr<vsomeip::payload> resp_pl =  vsomeip::runtime::get()->create_payload();
    std::vector<vsomeip::byte_t> pl_data(str.begin(), str.end());
    resp_pl->set_data(pl_data);
    resp->set_payload(resp_pl);

    // Send the response back
    app->send(resp);
    // we have finished
    //terminate();

}


void notify_test()
{
	char i = 'a';
	while (true) 
	{
		static std::string str("Notify notify_test");
		str = str + i;
		cout << str << endl;

		std::shared_ptr<vsomeip::payload> resp_pl =  vsomeip::runtime::get()->create_payload();
		std::vector<vsomeip::byte_t> pl_data(str.begin(), str.end());
		resp_pl->set_data(pl_data);

		//app->send(its_response);
		app->notify(SERVICE_ID,
			SERVICE_INSTANCE_ID,
			SERVICE_EVENT_ID, 
			resp_pl);
		std::this_thread::sleep_for(std::chrono::milliseconds(1000));
	}
}

int main()
{
    app = runtime::get()->create_application("server_sample");
    app->init();
    app->offer_service(SERVICE_ID, SERVICE_INSTANCE_ID);
	app->register_message_handler(SERVICE_ID, SERVICE_INSTANCE_ID,
        SERVICE_METHOD_ID,
        std::bind(&on_message_cbk,
                std::placeholders::_1));
    std::set<vsomeip::eventgroup_t> its_groups;
    its_groups.insert(SERVICE_EVENT_GROUP_ID);
    app->offer_event(
            SERVICE_ID,
            SERVICE_INSTANCE_ID,
            SERVICE_EVENT_ID,
            its_groups,
            true);
	thread nty_thrd = thread(&notify_test);
	thread napp_thrd = thread(&application::start, app);
	nty_thrd.join();
	napp_thrd.join();

    return 0;
}